package labox.innovation.gameserver.model;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import labox.innovation.config.Config;
import labox.innovation.db.core.L2DatabaseFactory;
import labox.innovation.gameserver.ai.CtrlIntention;
import labox.innovation.gameserver.datatables.ItemTable;
import labox.innovation.gameserver.model.actor.L2Character;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;
import labox.innovation.gameserver.model.actor.knownlist.NullKnownList;
import labox.innovation.gameserver.model.itemcontainer.PcInventory;
import labox.innovation.gameserver.network.SystemMessageId;
import labox.innovation.gameserver.network.serverpackets.ActionFailed;
import labox.innovation.gameserver.network.serverpackets.InventoryUpdate;
import labox.innovation.gameserver.network.serverpackets.SpawnItem;
import labox.innovation.gameserver.network.serverpackets.SystemMessage;
import labox.innovation.gameserver.skills.funcs.AttributeStringSplice;
import labox.innovation.gameserver.skills.funcs.Func;
import labox.innovation.gameserver.templates.item.ItemBouns;
import labox.innovation.gameserver.templates.item.ItemCreateFactory;
import labox.innovation.gameserver.templates.item.L2Armor;
import labox.innovation.gameserver.templates.item.L2ArmorType;
import labox.innovation.gameserver.templates.item.L2EtcItem;
import labox.innovation.gameserver.templates.item.L2EtcItemType;
import labox.innovation.gameserver.templates.item.L2Item;
import labox.innovation.gameserver.templates.item.L2Weapon;
import labox.innovation.gameserver.templates.item.L2WeaponType;
import labox.innovation.gameserver.timer.Timer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class manages items.
 *
 * @version $Revision: 1.4.2.1.2.11 $ $Date: 2005/03/31 16:07:50 $
 */
public final class L2ItemInstance extends L2Object {

	protected static final Logger _log = LoggerFactory.getLogger(L2ItemInstance.class.getName());

	public static final float REDUCEENRU_NUMS = 0.03f;

	/** Enumeration of locations for item */
	public static enum ItemLocation {
		VOID, //在地上
		INVENTORY, //玩家包里
		PAPERDOLL, //装备在身上
		WAREHOUSE, //再仓库 
		CLANWH, //在血盟仓库
		PET, //在宠物包里
		PET_EQUIP, //宠物装备上
		LEASE, //?
		FREIGHT, //?
		NPC,
		CONSIGNMENT  //寄售系统中
		//npc上
	}

	/**
	 * 物品 品质等级枚举
	 * @author zjj
	 *
	 */
	public static enum ItemGradeType {
		TALISMAN(0, 0f, "法器"), //法器
		BAODEVICE(1, 0.2f, "宝器"), //宝器
		LINGDEVICE(2, 0.5f, "灵器"), //灵器
		TREASURE(3, 0.9f, "至宝"), //至宝
		HORL(4, 1.4f, "神器"); //神器

		//附加属性个数
		private int _randAttiNums;

		private float _factor;

		private String _name;

		ItemGradeType(int nums, float factor, String name) {
			_randAttiNums = nums;
			_factor = factor;
			_name = name;
		}

		public String getName() {
			return _name;
		}

		/**
		 *  获得品质的数量
		 * @return
		 */
		public int getRandAttiNum() {
			return _randAttiNums;
		}

		/**
		 * 获得 品质的 属性加成系数
		 * 用于装备生成时
		 * @return
		 */
		public float getFactor() {
			return _factor;
		}

	}

	private L2Character _owner;
	
	/** ID of the owner */
	//物品的拥有者
	private long _ownerId; //2

	/** Quantity of the item */
	//物品的叠加数量
	private int _count;//3

	/** Initial Quantity of the item */
	//物品的初始数量
	private int _initCount;

	/** Remaining time (in miliseconds) */
	//物品的存在时间
	private long _time;//4

	/** Quantity of the item can decrease */
	//数量是否能减少
	private boolean _decrease = false;//5

	/** ID of the item */
	//物品模板id       
	private final int _itemId; //5

	/** Object L2Item associated to the item */
	//物品模板
	private final L2Item _item;

	/** Location of the item : Inventory, PaperDoll, WareHouse */
	//物品存放的位置
	private ItemLocation _loc;//6

	/** Slot where item is stored : Paperdoll slot, inventory order ...*/
	private int _locData;//7

	/** Level of enchantment of the item */
	//物品的强化等级
	private int _enchantLevel;

	/** Wear Item */
	// 是否 试穿
	private boolean _wear;

	/** Shadow item */
	/** Shadow item = 幻影装备 */
	//	private int _mana=-1;                 //means life time for shadow items(幻影装备的持续时间)
	private boolean _consumingMana = false;

	private static final int MANA_CONSUMPTION_RATE = 60000;

	/** Custom item types (used loto, race tickets) */
	//普通物品 类型
	private int _type1;

	private int _type2;

	//掉落 或 丢弃时间
	private long _dropTime;

	public static final int CHARGED_NONE = 0;

	public static final int CHARGED_SOULSHOT = 1;

	public static final int CHARGED_SPIRITSHOT = 1;

	public static final int CHARGED_BLESSED_SOULSHOT = 2; // It's a really exists? ;-)

	public static final int CHARGED_BLESSED_SPIRITSHOT = 2;

	/** Item charged with SoulShot (type of SoulShot) */
	private int _chargedSoulshot = CHARGED_NONE;

	/** Item charged with SpiritShot (type of SpiritShot) */
	private int _chargedSpiritshot = CHARGED_NONE;

	private boolean _chargedFishtshot = false;

	public static final int UNCHANGED = 0;

	public static final int ADDED = 1;

	public static final int REMOVED = 3;
	
	public static final int EQUIP_MODIFIED = 4;

	public static final int MODIFIED = 2;

	//定义最后的改变行为
	private int _lastChange = 2; //1 ??, 2 modified, 3 removed //

	//是否存在DB中
	private boolean _existsInDb; // if a record exists in DB. 

	//是否已更新到Db中
	private boolean _storedInDb; // if DB data is up-to-date.

	private final ReentrantLock _dbLock = new ReentrantLock();

	//战利品(掉落物品的管理)
	private Timer itemLootShedule;

	//物品生命周期
	public Timer _lifeTimeTask;

	private int _endurance; //当前耐久值//8
	
	private int _currentStoreExp = 0;   //存储的经验值

	private boolean _isbinding; //是否已绑定//9

	private int _startlevel; //追星级别//10

	private int _holenums; //当前孔数//11

	private ItemGradeType _itemgrade; //物品 品质//12

	// 物品 附加属性器
	private Map<Integer, ItemBouns> _itembouns;

	private boolean isIdentify = false; //是否已鉴定 //16

	private boolean isInscribe = false; //是否已铭刻//17

	/**
	 * 更新存储的经验值
	 * @param val
	 */
	public void updateStoreExp( int val ){
		
		setStoreExp( _currentStoreExp + val );
		
	}
	
	public void setStoreExp( int val ){
		
		if( !isEtcItem() ){
			return;
		}
		
		L2EtcItem it = (L2EtcItem)_item;
		
		if( it.getMaxStoreExp() <= 0 ){
			return;
		}
		
		_currentStoreExp = val;
		
		if( _currentStoreExp > it.getMaxStoreExp() ){
			_currentStoreExp = it.getMaxStoreExp();
		}	
		
	}
	
	public int getStoreExp(){
		return _currentStoreExp;
	}
	
	/**
	 *  是否已鉴定
	 * @return
	 */
	public boolean isIdentify() {
		return isIdentify;
	}

	public void setIdentify(boolean bl) {
		isIdentify = bl;
	}

	/**
	 * 是否已铭刻
	 * @return
	 */
	public boolean isInscribe() {
		return isInscribe;
	}

	public void setInscribe(boolean bl) {
		isInscribe = bl;
	}
	
	public void addItemBounsByDb(ItemBouns itembouns){
		
		if (_itembouns == null) {
			_itembouns = new HashMap<Integer, ItemBouns>();
		}

		_itembouns.put(itembouns.getItemBounsType().ordinal(), itembouns);
		
	}

	/**
	 * 添加 物品其他辅助 系统
	 * @param itembouns
	 */
	public void addItemBouns(ItemBouns itembouns) {
		if (_itembouns == null) {
			_itembouns = new HashMap<Integer, ItemBouns>();
		}

		_itembouns.put(itembouns.getItemBounsType().ordinal(), itembouns);
		_log.info("锻造物品: 物品 " + getName() + "(" + getObjectId() + ")新的" + itembouns.getItemBounsType() + itembouns.getAttributeDescribe(), getObjectId(), getName() );
	}
	
	public void removeItemBouns( int bounsType ){
		if (_itembouns != null) {
			_itembouns.remove( bounsType );
		}
	}
	
	/**
	 * 增加物品身上的所有的属性状态
	 */
	protected void addAllBouns(){
		
		_owner = FuzeWorld.getInstance().getPlayer( _ownerId );
		
		if( _owner != null ){
			
			_owner.addStatFuncs( getStatFuncs(_owner) );
			if( _itembouns != null )
				for( ItemBouns tb : _itembouns.values() ){
					tb.applyBouns( _owner);
				}
			
		}
		
	}// end addAllBouns
	
	/**
	 * 移除角色身上的所有属性加成
	 */
	protected void removeAllBouns(){
		
		_owner = FuzeWorld.getInstance().getPlayer( _ownerId );

		if( _owner != null ){
			
			_owner.removeStatsOwner( this );
			if( _itembouns != null )
				for( ItemBouns tb : _itembouns.values() ){
					tb.removeBouns( _owner);
				}
			
		}
		
	}// end removeAllBouns

	/**
	 * 获得 物品上的 物品附加系统
	 * @return
	 */
	public Map<Integer, ItemBouns> getItemBouns() {
		return _itembouns;
	}

	/**
	 * 获得指定的 物品辅助系统
	 * @param imask : 系统标识码
	 * @return
	 */
	public ItemBouns getItemBouns(int imask) {
		if (_itembouns == null) {
			return null;
		}
		return _itembouns.get(imask);
	}

	/**
	 * Constructor of the L2ItemInstance from the objectId and the itemId.
	 * @param objectId : int designating the ID of the object in the world
	 * @param itemId : int designating the ID of the item
	 */
	public L2ItemInstance(long objectId, int itemId) {
		super(objectId);
		_itemId = itemId;
		_item = ItemTable.getInstance().getTemplate(itemId);
		if (_itemId == 0 || _item == null)
			throw new IllegalArgumentException();
		super.setName(_item.getName());
		setCount(1);
		_loc = ItemLocation.VOID;
		_type1 = 0;
		_type2 = 0;
		_dropTime = 0;

		if (_item.getItemGrade() >= 0)
			_itemgrade = ItemGradeType.values()[_item.getItemGrade()];
		_holenums = 0;
		_startlevel = 0;
		_endurance = _item.getEnduranceup();

		//		_mana = _item.getDuration();
		_time = _item.getTime() == -1 ? -1 : System.currentTimeMillis() + ((long) _item.getTime() * 60 * 1000);
//		scheduleLifeTimeTask();
	}

	/**
	 * Constructor of the L2ItemInstance from the objetId and the description of the item given by the L2Item.
	 * @param objectId : int designating the ID of the object in the world
	 * @param item : L2Item containing informations of the item
	 */
	public L2ItemInstance(long objectId, L2Item item) {
		super(objectId);
		_itemId = item.getItemId();
		_item = item;
		if (_itemId == 0)
			throw new IllegalArgumentException();
		super.setName(_item.getName());
		setCount(1);
		_loc = ItemLocation.VOID;
		if (_item.getItemGrade() >= 0)
			_itemgrade = ItemGradeType.values()[_item.getItemGrade()];
		_endurance = _item.getEnduranceup();
		//		_mana = _item.getDuration();
		_time = _item.getTime() == -1 ? -1 : System.currentTimeMillis() + ((long) _item.getTime() * 60 * 1000);
//		scheduleLifeTimeTask();
	}

	@Override
	public void initKnownList() {
		setKnownList(new NullKnownList(this));
	}

	/**
	 * Remove a L2ItemInstance from the world and send server->client GetItem packets.<BR><BR>
	 *
	 * <B><U> Actions</U> :</B><BR><BR>
	 * <li>Send a Server->Client Packet GetItem to player that pick up and its _knowPlayers member </li>
	 * <li>Remove the L2Object from the world</li><BR><BR>
	 *
	 * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T REMOVE the object from _allObjects of L2World </B></FONT><BR><BR>
	 *
	 * <B><U> Assert </U> :</B><BR><BR>
	 * <li> this instanceof L2ItemInstance</li>
	 * <li> _worldRegion != null <I>(L2Object is visible at the beginning)</I></li><BR><BR>
	 *
	 * <B><U> Example of use </U> :</B><BR><BR>
	 * <li> Do Pickup Item : PCInstance and Pet</li><BR><BR>
	 *
	 * @param player Player that pick up the item
	 *
	 */
	public final void pickupMe(L2Character player) {
		if (Config.ASSERT)
			assert getPosition().getSceneRegion() != null;

		SceneRegion oldregion = getPosition().getSceneRegion();

		// Create a server->client GetItem packet to pick up the L2ItemInstance
		//		GetItem gi = new GetItem(this, player.getObjectId());
		//		player.broadcastPacket(gi);

		setIsVisible(false);
		FuzeWorld.getInstance().removeVisibleObject(this);

		// if this item is a mercenary ticket, remove the spawns!
		int itemId = getItemId();

		//		if (MercTicketManager.getInstance().getTicketCastleId(itemId) > 0) {
		//			MercTicketManager.getInstance().removeTicket(this);
		//			ItemsOnGroundManager.getInstance().removeObject(this);
		//		}

		// outside of synchronized to avoid deadlocks
		// Remove the L2ItemInstance from the world
		//		WorldManager.getInstance().removeVisibleObject(this, oldregion);
		FuzeWorld.getInstance().removeVisibleObject(this);
	}

	/**
	 * Sets the ownerID of the item
	 * @param process : String Identifier of process triggering this action
	 * @param owner_id : int designating the ID of the owner
	 * @param creator : L2PcInstance Player requesting the item creation
	 * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 */
	public void setOwnerId(String process, long owner_id, FuzePcInstance creator, L2Object reference) {
		setOwnerId(owner_id);

//		if (Config.LOG_ITEMS) {
			//			LogRecord record = new LogRecord(Level.INFO, "CHANGE:" + process);
			//			record.setLoggerName("item");
			//			record.setParameters(new Object[] { this, creator, reference });
			//			_logItems.log(record);
			_log.info("CHANGE:" + process + " item:" + this.getName() + "(" + getObjectId() + ")" + " 角色:" + creator.getName() + "(" + creator.getObjectId() + ")", getObjectId(), getName());
//		}

		if (creator != null) {
			if (creator.isGM()) {
				String referenceName = "no-reference";
				if (reference != null) {
					referenceName = (reference.getName() != null ? reference.getName() : "no-name");
				}
				String targetName = (creator.getTarget() != null ? creator.getTarget().getName() : "no-target");
//				if (Config.GMAUDIT)
//					GMAudit.auditGMAction(creator.getName(), process + "(id: " + getItemId() + " name: " + getName() + ")", targetName, "L2Object referencing this action is: " + referenceName);
			}
		}
	}

	/**
	 * Sets the ownerID of the item
	 * @param owner_id : int designating the ID of the owner
	 */
	public void setOwnerId(long owner_id) {
		if (owner_id == _ownerId)
			return;

		_ownerId = owner_id;
		_storedInDb = false;
	}

	/**
	 * Returns the ownerID of the item
	 * @return int : ownerID of the item
	 */
	public long getOwnerId() {
		return _ownerId;
	}

	/**
	 * Sets the location of the item
	 * @param loc : ItemLocation (enumeration)
	 */
	public void setLocation(ItemLocation loc) {
		setLocation(loc, 0);
	}

	/**
	 * Sets the location of the item.<BR><BR>
	 * <U><I>Remark :</I></U> If loc and loc_data different from database, say datas not up-to-date
	 * @param loc : ItemLocation (enumeration)
	 * @param loc_data : int designating the slot where the item is stored or the village for freights
	 */
	public void setLocation(ItemLocation loc, int loc_data) {
		if (loc == _loc && loc_data == _locData)
			return;
		_loc = loc;
		_locData = loc_data;
		_storedInDb = false;
	}

	public ItemLocation getLocation() {
		return _loc;
	}

	/**
	 * Sets the quantity of the item.<BR><BR>
	 * @param count the new count to set
	 */
	public void setCount(int count) {
		if (getCount() == count) {
			return;
		}

		if( count > _item.getMaxStackNums() ){
			count = _item.getMaxStackNums();
		}
		_count = count >= 0 ? count : 0;
		_storedInDb = false;
	}

	/**
	 * @return Returns the count.
	 */
	public int getCount() {
		return _count;
	}

	/**
	 * Sets the quantity of the item.<BR><BR>
	 * <U><I>Remark :</I></U> If loc and loc_data different from database, say datas not up-to-date
	 * @param process : String Identifier of process triggering this action
	 * @param count : int
	 * @param creator : L2PcInstance Player requesting the item creation
	 * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 */
	public void changeCount(String process, int count, FuzePcInstance creator, L2Object reference) {
		if (count == 0) {
			return;
		}

//		int max = getItemId() == ADENA_ID ? MAX_ADENA : Integer.MAX_VALUE;
		int max = getItem().getMaxStackNums();

		if (count > 0 && getCount() > max - count) {
			setCount(max);
		} else {
			setCount(getCount() + count);
		}

		if (getCount() < 0) {
			setCount(0);
		}

		_storedInDb = false;

//		if (Config.LOG_ITEMS) {
			//			LogRecord record = new LogRecord(Level.INFO, "CHANGE:" + process);
			//			record.setLoggerName("item");
			//			record.setParameters(new Object[] { this, creator, reference });
			//			_logItems.log(record);
			_log.info("改变物品数:" + process + "物品名 " + this.getName() + "(" + getObjectId() +")" + "数量:" + getCount() ,getObjectId(), getName() );
//		}

		if (creator != null) {
			if (creator.isGM()) {
				String referenceName = "no-reference";
				if (reference != null) {
					referenceName = (reference.getName() != null ? reference.getName() : "no-name");
				}
				String targetName = (creator.getTarget() != null ? creator.getTarget().getName() : "no-target");
				//				if (Config.GMAUDIT)
				//					GMAudit.auditGMAction(creator.getName(), process + "(id: " + getItemId() + " objId: " + getObjectId() + " name: " + getName() + " count: " + count + ")", targetName, "L2Object referencing this action is: " + referenceName);
			}
		}
	}

	// No logging (function designed for shots only)
	public void changeCountWithoutTrace(int count, FuzePcInstance creator, L2Object reference) {
		this.changeCount(null, count, creator, reference);
	}

	/**
	 * Returns if item is equipable
	 * @return boolean
	 */
	public boolean isEquipable() {
		return !(_item.getBodyPart() == 0 || _item instanceof L2EtcItem);
	}

	/**
	 * Returns if item is equipped
	 * @return boolean
	 */
	public boolean isEquipped() {
		return _loc == ItemLocation.PAPERDOLL || _loc == ItemLocation.PET_EQUIP;
	}

	/**
	 * 是否是钱
	 * @return
	 */
	public boolean isMoney() {
		return getItem().isMoney();
	}

	/**
	 * Returns the slot where the item is stored
	 * @return int
	 */
	public int getLocationSlot() {
		if (Config.ASSERT)
			assert _loc == ItemLocation.PAPERDOLL || _loc == ItemLocation.PET_EQUIP || _loc == ItemLocation.FREIGHT || _loc == ItemLocation.INVENTORY;
		return _locData;
	}

	/**
	 * Returns the characteristics of the item
	 * @return L2Item
	 */
	public L2Item getItem() {
		return _item;
	}

	public int getCustomType1() {
		return _type1;
	}

	public int getCustomType2() {
		return _type2;
	}

	public void setCustomType1(int newtype) {
		_type1 = newtype;
	}

	public void setCustomType2(int newtype) {
		_type2 = newtype;
	}

	public void setDropTime(long time) {
		_dropTime = time;
	}

	public long getDropTime() {
		return _dropTime;
	}

	public boolean isWear() {
		return _wear;
	}

	public void setWear(boolean newwear) {
		_wear = newwear;
	}

	/**
	 * Returns the type of item
	 * @return Enum
	 */
	@SuppressWarnings("unchecked")
	public Enum getItemType() {
		return _item.getItemType();
	}

	/**
	 * 物品 能否被修理
	 * @return
	 */
	public boolean canRepair() {
		return getItem().getCanrepair();
	}

	/**
	 * Returns the ID of the item
	 * @return int
	 */
	public int getItemId() {
		return _itemId;
	}

	@SuppressWarnings("unchecked")
	public int getItemWeight() {
		Enum type = _item.getItemType();

		if (type instanceof L2EtcItemType) {
			//如果是道具  那么返回-1
			return -1;
		} else if (type instanceof L2ArmorType) {
			return ((L2ArmorType) type).getWeight();
		} else if (type instanceof L2WeaponType) {
			return ((L2WeaponType) type).getWeight();
		}

		return -1;

	}// end 

	/**
	 *  获得物品等级
	 * @return
	 */
	public int getItemLvl() {
		return _item.getItemLvl();
	}

	/**
	 * Returns true if item is an EtcItem
	 * @return boolean
	 */
	public boolean isEtcItem() {
		return (_item instanceof L2EtcItem);
	}
	
	/**
	 * 是否是存储经验的道具
	 * @return
	 */
	public boolean isStoreExpItem(){
		
		if( isEtcItem() ){
			L2EtcItem it = (L2EtcItem)_item;
			return it.getItemType() == L2EtcItemType.STOREEXP;
		}
		
		return false;
	}

	/**
	 * Returns true if item is a Weapon/Shield
	 * @return boolean
	 */
	public boolean isWeapon() {
		return (_item instanceof L2Weapon);
	}

	/**
	 * Returns true if item is an Armor
	 * @return boolean
	 */
	public boolean isArmor() {
		return (_item instanceof L2Armor);
	}

	/**
	 * Returns the characteristics of the L2EtcItem
	 * @return L2EtcItem
	 */
	public L2EtcItem getEtcItem() {
		if (_item instanceof L2EtcItem) {
			return (L2EtcItem) _item;
		}
		return null;
	}

	/**
	 * Returns the characteristics of the L2Weapon
	 * @return L2Weapon
	 */
	public L2Weapon getWeaponItem() {
		if (_item instanceof L2Weapon) {
			return (L2Weapon) _item;
		}
		return null;
	}

	/**
	 * Returns the characteristics of the L2Armor
	 * @return L2Armor
	 */
	public L2Armor getArmorItem() {
		if (_item instanceof L2Armor) {
			return (L2Armor) _item;
		}
		return null;
	}

	/**
	 *  获得 枚举的类型名 字符串
	 * @return
	 */
	public String getItemTypeString() {
		return _item.getItemType().toString();
	}

	/**
	 * Returns the quantity of crystals for crystallization
	 * 
	 * @return int
	 */
	public final int getCrystalCount() {
		//		return _item.getCrystalCount(_enchantLevel);
		return 0;
	}

	/**
	 * Returns the reference price of the item
	 * @return int
	 */
	public int getReferencePrice() {
		return _item.getReferencePrice();
	}

	/**
	 * Returns the name of the item
	 * @return String
	 */
	public String getItemName() {
		return _item.getName();
	}

	/**
	 * Returns the last change of the item
	 * @return int
	 */
	public int getLastChange() {
		return _lastChange;
	}

	/**
	 * Sets the last change of the item
	 * @param lastChange : int
	 */
	public void setLastChange(int lastChange) {
		_lastChange = lastChange;
	}

	/**
	 * 返回是否是可堆叠的
	 * @return boolean
	 */
	public boolean isStackable() {
		return _item.isStackable();
	}
	
	/**
	 * 能否在叠加 nums的数
	 * @param nums
	 * @return
	 */
	public boolean canStackable( int nums ){
		if( !isStackable() ){
			return false;
		}
		
		if( isMoney() ){
			return true;
		}
		
		return _item.getMaxStackNums() >= ( nums + getCount() );
	}

	/**
	 * Returns if item is dropable
	 * @return boolean
	 */
	public boolean isDropable() {
		//		return isAugmented() ? false : _item.isDropable();
		return _item.isDropable();
	}

	/**
	 * Returns if item is destroyable
	 * @return boolean
	 */
	public boolean isDestroyable() {
		return _item.isDestroyable();
	}

	/**
	 * Returns if item is tradeable
	 * @return boolean
	 */
	public boolean isTradeable() {
		//		return isAugmented() ? false : _item.isTradeable();
		return _item.isTradeable();
	}

	/**
	 * Returns if item is sellable
	 * @return boolean
	 */
	public boolean isSellable() {
		//		return isAugmented() ? false : _item.isSellable();
		return _item.isSellable();
	}

	/**
	 * Returns if item can be deposited in warehouse or freight
	 * @return boolean
	 */
	public boolean isDepositable() {
		// equipped, hero and quest items
		return _item.isDepositable();

	}

	/**
	 * Returns if item is consumable
	 * @return boolean
	 */
	public boolean isConsumable() {
		return _item.isConsumable();
	}

	public boolean isHeroItem() {
		return _item.isHeroItem();
	}

	public boolean isCommonItem() {
		return _item.isCommon();
	}

	/**
	 * Returns whether this item is pvp or not
	 * @return boolean
	 */
	public boolean isPvp() {
		return _item.isPvpItem();
	}

	public boolean isOlyRestrictedItem() {
		return (Config.LIST_OLY_RESTRICTED_ITEMS.contains(_itemId));
	}

	/**
	 * Returns if item is available for manipulation
	 * @return boolean
	 */
	public boolean isAvailable(FuzePcInstance player, boolean allowMoney, boolean allowNonTradeable) {
		return ((!isEquipped()) // Not equipped
				&& (getItem().getType2() != L2Item.TYPE2_QUEST) // Not Quest Item
				&& (getItem().getType2() != 4 || getItem().getType1() != 1) // TODO: what does this mean?
				&& (player.getPet() == null || getObjectId() != player.getPet().getControlItemId()) // Not Control item of currently summoned pet
				
				&& (allowMoney || (getItemId() != PcInventory.MONEY_SLIVER_ID && getItemId() != PcInventory.MONEY_NOTE_ID && getItemId() != PcInventory.MONEY_YAUNBAO_ID)) // Not adena

		&& (allowNonTradeable || isTradeable()));
	}

	/* (non-Javadoc)
	 * @see labox.innovation.gameserver.model.L2Object#onAction(labox.innovation.gameserver.model.L2PcInstance)
	 * also check constraints: only soloing castle owners may pick up mercenary tickets of their castle
	 */
	@Override
	public void onAction(FuzePcInstance player) {
		// this causes the validate position handler to do the pickup if the location is reached.
		// mercenary tickets can only be picked up by the castle owner.
		//		int castleId = MercTicketManager.getInstance().getTicketCastleId(_itemId);

		if (player.isInParty()) {
			if (player.isInParty()) //do not allow owner who is in party to pick tickets up
				player.sendMessage("You cannot pickup mercenaries while in a party.");
			else
				player.sendMessage("Only the castle lord can pickup mercenaries.");

			player.setTarget(this);
			player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
			// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
			player.sendPacket(ActionFailed.STATIC_PACKET);
		} else
			player.getAI().setIntention(CtrlIntention.AI_INTENTION_PICK_UP, this);
	}

	/**
	 * Returns the level of enchantment of the item
	 * @return int
	 */
	public int getEnchantLevel() {
		return _enchantLevel;
	}

	/**
	 * Sets the level of enchantment of the item
	 * @param int
	 */
	public void setEnchantLevel(int enchantLevel) {
		if (_enchantLevel == enchantLevel)
			return;
		_enchantLevel = enchantLevel;
		_storedInDb = false;
	}

	/**
	 * Returns the physical defense of the item
	 * @return int
	 */
	public int getPDef() {
		//		if (_item instanceof L2Armor)
		//			return ((L2Armor) _item).getPDef();
		return 0;
	}

	/**
	 * 获得当前的耐久值
	 * @return
	 */
	public int getEndurance() {
		return _endurance;
	}

	/**
	 * 获得耐久值上限
	 * @return
	 */
	public int getEnduranceUp() {
		return _item.getEnduranceup();
	}

	/**
	 * 是否有耐久
	 * @return
	 */
	public boolean hasEndurance() {
		return _item.getEnduranceup() != -1;
	}

	/**
	 * 设置耐久值
	 * @param endurance
	 * @return
	 */
	public void setEndurance(int endurance) {
		if (getEnduranceUp() < endurance) {
			endurance = getEnduranceUp();			
		} else if (endurance < 0 ) {
			
			if( _endurance <= 0 ){
				return;
			}
			
			endurance = 0;
			//如果耐久度小于0 那么移除掉所有的装备属性加成
			if( isEquipped() ){
				
				if( _log.isDebugEnabled() ){
					_log.debug("耐久度小于等于0:" + "移除掉装备上的属性" );
				}
				removeAllBouns();
				
			}
			
		}//
		
//		System.out.println("当前耐久度:" + _endurance + "新耐久度:" + endurance + "装备是否装备:" + isEquipped() );
		if( _endurance <=0 &&  endurance > 0 ){
//			System.out.println("增加装备状态属性");
			
			if( isEquipped() ){
				
				if( _log.isDebugEnabled() ){
					_log.debug("耐久度大于0:" + "恢复掉装备上的属性" );
				}
				
				addAllBouns();
			}// 
				
		}
		
		_endurance = endurance;
		
	}

	/**
	 * 减少耐久度
	 * @param endurance
	 */
	public void reduceEndurance(int endurance) {
		//如果耐久度已为0  那么 不在减耐久精度
		if( _endurance <= 0 ){
			return;
		}
		_endurance = _endurance - endurance;
		if (_endurance <= 0) {
			_endurance = 0;
			
			//如果耐久度小于0 那么移除掉所有的装备属性加成
			if( isEquipped() ){
				if( _log.isDebugEnabled() ){
					_log.debug("耐久度小于等于0:" + "移除掉装备上的属性" );
				}
				removeAllBouns();
			}
				
		}// 
		
	}// end

	/**
	 *  获得物品展示Id
	 * @return
	 */
	public int getDisplayIconId() {
		return _item.getDisplayIconId();
	}

	public void restoreAttributes() {
		Connection con = null;
		try {
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT augAttributes,augSkillId,augSkillLevel,elemType,elemValue FROM item_attributes WHERE itemId=?");
			statement.setLong(1, getObjectId());
			ResultSet rs = statement.executeQuery();
			rs = statement.executeQuery();
			if (rs.next()) {
				int aug_attributes = rs.getInt(1);
				int aug_skillId = rs.getInt(2);
				int aug_skillLevel = rs.getInt(3);
			}
			rs.close();
			statement.close();
		} catch (Exception e) {
			_log.error("Could not restore augmentation and elemental data for item " + getObjectId() + " from DB: " + e.getMessage(), Config.SERVER_ID, e);
		} finally {
			try {
				con.close();
			} catch (Exception e) {
			}
		}
	}

	public void updateItemAttributes() {
		Connection con = null;
		try {
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("REPLACE INTO item_attributes VALUES(?,?,?,?,?,?)");
			statement.setLong(1, getObjectId());

			statement.executeUpdate();
			statement.close();
		} catch (Exception e) {
			_log.error("Could not remove elemental enchant for item: " + getObjectId() + " from DB:", Config.SERVER_ID,e);
		} finally {
			try {
				con.close();
			} catch (Exception e) {
			}
		}
	}

	/**
	 * Used to decrease mana
	 * (mana means life time for shadow items)
	 */
	public class ScheduleConsumeManaTask implements Runnable {
		private final L2ItemInstance _shadowItem;

		public ScheduleConsumeManaTask(L2ItemInstance item) {
			_shadowItem = item;
		}

		public void run() {
			try {
				// decrease mana
				if (_shadowItem != null)
					_shadowItem.decreaseMana(true);
			} catch (Exception e) {
				_log.error("", Config.SERVER_ID, e);
			}
		}
	}

	/**
	 * Returns true if this item is a shadow item
	 * Shadow items have a limited life-time
	 * @return
	 */
	public boolean isShadowItem() {
		//		return (_mana >= 0);
		return false;
	}

	/**
	 * Returns the remaining mana of this shadow item
	 * @return lifeTime
	 */
	public int getMana() {
		//		return _mana;
		return 0;
	}

	/**
	 * Decreases the mana of this shadow item,
	 * sends a inventory update
	 * schedules a new consumption task if non is running
	 * optionally one could force a new task
	 * @param forces a new consumption task if item is equipped
	 */
	public void decreaseMana(boolean resetConsumingMana) {
		if (!isShadowItem())
			return;

		//		if (_mana > 0)
		//			_mana--;

		if (_storedInDb)
			_storedInDb = false;
		if (resetConsumingMana)
			_consumingMana = false;

		FuzePcInstance player = ((FuzePcInstance) FuzeWorld.getInstance().findObject(getOwnerId()));

		//		if (player != null) {
		//			SystemMessage sm;
		//			switch (_mana) {
		//			case 10:
		//				sm = new SystemMessage(SystemMessageId.S1S_REMAINING_MANA_IS_NOW_10);
		//				sm.addItemName(_item);
		//				player.sendPacket(sm);
		//				break;
		//			case 5:
		//				sm = new SystemMessage(SystemMessageId.S1S_REMAINING_MANA_IS_NOW_5);
		//				sm.addItemName(_item);
		//				player.sendPacket(sm);
		//				break;
		//			case 1:
		//				sm = new SystemMessage(SystemMessageId.S1S_REMAINING_MANA_IS_NOW_1);
		//				sm.addItemName(_item);
		//				player.sendPacket(sm);
		//				break;
		//			}
		//
		//			if (_mana == 0) // The life time has expired
		//			{
		//				sm = new SystemMessage(SystemMessageId.S1S_REMAINING_MANA_IS_NOW_0);
		//				sm.addItemName(_item);
		//				player.sendPacket(sm);
		//
		//				// unequip
		//				if (isEquipped()) {
		//					L2ItemInstance[] unequiped = player.getInventory().unEquipItemInSlotAndRecord(getLocationSlot());
		//					InventoryUpdate iu = new InventoryUpdate();
		//					for (L2ItemInstance item : unequiped) {
		//						iu.addModifiedItem(item);
		//					}
		//					player.sendPacket(iu);
		//				}
		//
		//				if (getLocation() != ItemLocation.WAREHOUSE) {
		//					// destroy
		//					player.getInventory().destroyItem("L2ItemInstance", this, player, null);
		//
		//					// send update
		//					InventoryUpdate iu = new InventoryUpdate();
		//					iu.addRemovedItem(this);
		//					player.sendPacket(iu);
		//
		//					StatusUpdate su = new StatusUpdate(player.getObjectId());
		//					su.addAttribute(StatusUpdate.CUR_LOAD, player.getCurrentLoad());
		//					player.sendPacket(su);
		//
		//				} else {
		//					player.getWarehouse().destroyItem("L2ItemInstance", this, player, null);
		//				}
		//
		//				// delete from world
		//				WorldManager.getInstance().removeObject(this);
		//			} else {
		//				// Reschedule if still equipped
		//				if (!_consumingMana && isEquipped()) {
		//					scheduleConsumeManaTask();
		//				}
		//				if (getLocation() != ItemLocation.WAREHOUSE) {
		//					InventoryUpdate iu = new InventoryUpdate();
		//					iu.addModifiedItem(this);
		//					player.sendPacket(iu);
		//				}
		//			}
		//		}
	}

	public void scheduleConsumeManaTask() {
		if (_consumingMana)
			return;
		_consumingMana = true;
		Timer t = new Timer(MANA_CONSUMPTION_RATE, false, new ScheduleConsumeManaTask(this));
	}

	/**
	 * Returns false cause item can't be attacked
	 * @return boolean false
	 */
	@Override
	public boolean isAutoAttackable(L2Character attacker) {
		return false;
	}

	/**
	 * Returns the type of charge with SoulShot of the item.
	 * @return int (CHARGED_NONE, CHARGED_SOULSHOT)
	 */
	public int getChargedSoulshot() {
		return _chargedSoulshot;
	}

	/**
	 * Returns the type of charge with SpiritShot of the item
	 * @return int (CHARGED_NONE, CHARGED_SPIRITSHOT, CHARGED_BLESSED_SPIRITSHOT)
	 */
	public int getChargedSpiritshot() {
		return _chargedSpiritshot;
	}

	public boolean getChargedFishshot() {
		return _chargedFishtshot;
	}

	/**
	 * Sets the type of charge with SoulShot of the item
	 * @param type : int (CHARGED_NONE, CHARGED_SOULSHOT)
	 */
	public void setChargedSoulshot(int type) {
		_chargedSoulshot = type;
	}

	/**
	 * Sets the type of charge with SpiritShot of the item
	 * @param type : int (CHARGED_NONE, CHARGED_SPIRITSHOT, CHARGED_BLESSED_SPIRITSHOT)
	 */
	public void setChargedSpiritshot(int type) {
		_chargedSpiritshot = type;
	}

	public void setChargedFishshot(boolean type) {
		_chargedFishtshot = type;
	}

	/**
	 * This function basically returns a set of functions from
	 * L2Item/L2Armor/L2Weapon, but may add additional
	 * functions, if this particular item instance is enhanched
	 * for a particular player.
	 * @param player : L2Character designating the player
	 * @return Func[]
	 */
	public Func[] getStatFuncs(L2Character player) {

		//		Func [] funcList = getItem().getStatFuncs(this, player);
		//		
		//		//如果是非装备物品  不存在品质修改
		//		//由于装备存在品质等级。 品质会影响相应的 物品属性值
		//		if( !( _item instanceof L2EtcItem ) )
		//		{
		//			int isize = funcList.length;
		//			for( int i=0; i < isize; i++ )
		//			{
		//				funcList[ i ] = new FuncItem( _itemgrade, funcList[i] );
		//			}
		//			
		//		}
		//		
		//		return funcList;
		return getItem().getStatFuncs(this, player);
	}

	/**
	 * Updates the database.<BR>
	 */
//	public void updateDatabase() {
//		updateDatabase(false);
//	}

	/**
	 * Updates the database.<BR>
	 * 
	 * @param force if the update should necessarilly be done.
	 */
//	public void updateDatabase(boolean force) {
//		if (isWear()) //avoid saving weared items
//		{
//			return;
//		}
//
//		_dbLock.lock();
//		try {
//			if (_existsInDb) {
//				if (_ownerId == 0 || _loc == ItemLocation.VOID || (getCount() == 0 && _loc != ItemLocation.LEASE)) {
//					removeFromDb();
//				} else if (!Config.LAZY_ITEMS_UPDATE || force) {
//					updateInDb();
//				}
//			} else {
//				if (getCount() == 0 && _loc != ItemLocation.LEASE) {
//					return;
//				}
//				if (_loc == ItemLocation.VOID || _loc == ItemLocation.NPC || _ownerId == 0) {
//					return;
//				}
//				insertIntoDb();
//			}
//		} finally {
//			_dbLock.unlock();
//		}
//	}


	/**
	 * 把这个道具掉落到游戏世界中
	 * @param dropper 掉落者
	 * @param x 掉落的X
	 * @param y 掉落的Y
	 */
	public final void dropMe(L2Character dropper, int x, int y) {
		if (Config.ASSERT)
			assert getPosition().getSceneRegion() == null;
		int _x = 0, _y = 0;
		if (Config.GEODATA > 0 && dropper != null) {
			//			Location dropDest = dropper.getPosition().getScene().getGeoData().moveCheck( dropper.getX(), dropper.getY(), x, y, dropper.getInstanceId() );
			Location dropDest = dropper.getPosition().getScene().getGeoData().moveCheck(dropper.getX(), dropper.getY(), x, y);
			_x = dropDest.getX();
			_y = dropDest.getY();

		}

		if (dropper != null)
			setInstanceId(dropper.getInstanceId()); // 掉落到可见世界中的时候要设置副本ID
		else
			setInstanceId(0); //没有掉落者？那设置成一个全局道具

		synchronized (this) {
			// Set the x,y position of the L2ItemInstance dropped and update its _worldregion
			setIsVisible(true);
			getPosition().setScenePosition(_x, _y);
			FuzeWorld.getInstance().addVisibleObject(this, dropper.getScene());
			// Add the L2ItemInstance dropped to _visibleObjects of its L2WorldRegion
		}

		setDropTime(System.currentTimeMillis());

		//		if (Config.SAVE_DROPPED_ITEM)
		//			ItemsOnGroundManager.getInstance().save(this);

	}





	@Override
	public String toString() {
		return "L2ItemInstance [_chargedFishtshot=" + _chargedFishtshot + ", _chargedSoulshot=" + _chargedSoulshot + ", _chargedSpiritshot=" + _chargedSpiritshot + ", _consumingMana=" + _consumingMana + ", _count=" + _count + ", _dbLock=" + _dbLock + ", _decrease=" + _decrease + ", _dropTime=" + _dropTime + ", _enchantLevel=" + _enchantLevel + ", _endurance=" + _endurance + ", _existsInDb=" + _existsInDb + ", _holenums=" + _holenums + ", _initCount=" + _initCount + ", _isbinding=" + _isbinding + ", _item=" + _item + ", _itemId=" + _itemId + ", _itembouns=" + _itembouns + ", _itemgrade=" + _itemgrade + ", _lastChange=" + _lastChange + ", _lifeTimeTask=" + _lifeTimeTask + ", _loc=" + _loc + ", _locData=" + _locData + ", _ownerId=" + _ownerId + ", _startlevel=" + _startlevel + ", _storedInDb=" + _storedInDb + ", _time=" + _time + ", _type1=" + _type1 + ", _type2=" + _type2 + ", _wear=" + _wear + ", isIdentify=" + isIdentify + ", isInscribe=" + isInscribe + ", itemLootShedule="
				+ itemLootShedule + "]";
	}

	public void resetOwnerTimer() {
		if (itemLootShedule != null)
			itemLootShedule.cancel();
		itemLootShedule = null;
	}

	public void setItemLootShedule(Timer sf) {
		itemLootShedule = sf;
	}

	public Timer getItemLootShedule() {
		return itemLootShedule;
	}

	public boolean isNightLure() {
		return ((_itemId >= 8505 && _itemId <= 8513) || _itemId == 8485);
	}

	public void setCountDecrease(boolean decrease) {
		_decrease = decrease;
	}

	public boolean getCountDecrease() {
		return _decrease;
	}

	public void setInitCount(int InitCount) {
		_initCount = InitCount;
	}

	public long getInitCount() {
		return _initCount;
	}

	public void restoreInitCount() {
		if (_decrease)
			setCount(_initCount);
	}

	public boolean isTimeLimitedItem() {
		return (_time > 0);
	}

	/**
	 * 获得物品 品质级
	 * @return
	 */
	public int getItemGrade() {
		if (_itemgrade == null) {
			if( isEtcItem() ){
				return ItemCreateFactory.ETCITEM_GRADE ;
			}else{
				
				return -1;
			}
			
		}
		return _itemgrade.ordinal();
	}

	public ItemGradeType getItemGradeType() {
		return _itemgrade;
	}

	/**
	 *  获得品质加成系数
	 * @return
	 */
	public float getItemGradeFactor() {
		return 1 + _itemgrade.getFactor();
	}

	/**
	 * 设置 物品的品质
	 * @param imask : 品质索引
	 */
	public void setItemGrade(int imask) {
		if (imask < ItemGradeType.values().length && imask > -1)
			_itemgrade = ItemGradeType.values()[imask];
		else if( imask != ItemCreateFactory.ETCITEM_GRADE ){
			_itemgrade = null;
			_log.warn("物品品质不对.物品名:" + getName() + "(" + getObjectId() + ") 品质下标为:" + imask, Config.SERVER_ID);
		}
			
	}

	/**
	 * 设置装备星级
	 * @param lvl
	 */
	public void setItemStarLvl(int lvl) {
		_startlevel = lvl;
	}

	public ItemLocation get_loc() {
		return _loc;
	}

	/**
	 * 设置槽位
	 * @param loc
	 */
	public void set_loc(ItemLocation loc) {
		_loc = loc;
	}

	public int get_locData() {
		return _locData;
	}

	/**
	 * 设置道具位置类型
	 * @param locData
	 */
	public void set_locData(int locData) {
		_locData = locData;
	}

	/**
	 *  是否绑定
	 * @return
	 */
	public boolean isBinding() {
		return _isbinding;
	}

	public void setBinding(boolean binding) {
		_isbinding = binding;
	}

	/**
	 * 获得 当前追星等级
	 * @return
	 */
	public int getStarLvl() {
		return _startlevel;
	}

	public void setStarLvl(int lvl) {
		_startlevel = lvl;
	}

	/**
	 *  获得当前 孔数
	 * @return
	 */
	public int getHoleNums() {
		return _holenums;
	}

	public void setHoleNum(int nums) {
		_holenums = nums;
	}

	/**
	 *  获得装备的属性描述
	 * @return
	 */
	public String getAttriDescriptoin() {
		StringBuilder sb = new StringBuilder();
//		sb.append("<form tl='物品描述'>");
		sb.append(AttributeStringSplice.getInstance().getAttributeString(this));
		sb.append(_item.getAttributString());

		if (_itembouns != null) {
//			System.out.println("附加属性");
			Iterator<Map.Entry<Integer, ItemBouns>> it = _itembouns.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry<Integer, ItemBouns> mapEn = it.next();
				ItemBouns tb = mapEn.getValue();
				sb.append(tb.getAttributeDescribe());
			}
		}

		sb.append(getItem().getItemDes()).append("<br/>");
//		sb.append("</form>");
		return sb.toString();
	}
	
	/**
	 *  获得物品的冷却类型
	 *  -1表示 不受物品冷却类型影响
	 * @return
	 */
	public final int getCatCool() {
		return _item.getCatCool();
	}

	/**
	 *  获得物品 公共CD的冷去类型
	 *  -1表示  没有公共CD影响
	 * @return
	 */
	public final int getGlobalCatCool() {
		return _item.getGlobalCatCool();
	}

	/**
	 * Returns (current system time + time) of this time limited item
	 * @return Time
	 */
	public long getTime() {
		return _time;
	}

	public int getRemainingTime() {
		return (int) (_time - System.currentTimeMillis());
	}

	public void endOfLife() {
		FuzePcInstance player = ((FuzePcInstance) FuzeWorld.getInstance().findObject(getOwnerId()));
		if (player != null) {
			if (isEquipped()) {
				L2ItemInstance[] unequiped = player.getInventory().unEquipItemInSlotAndRecord(getLocationSlot());
				InventoryUpdate iu = new InventoryUpdate();
				for (L2ItemInstance item : unequiped) {
					iu.addModifiedItem(item);
				}
				player.sendPacket(iu);
			}

			if (getLocation() != ItemLocation.WAREHOUSE) {
				// destroy
				player.getInventory().destroyItem("L2ItemInstance", this, player, null);

				// send update
				InventoryUpdate iu = new InventoryUpdate();
				iu.addRemovedItem(this);
				player.sendPacket(iu);

			} else {
				player.getWarehouse().destroyItem("L2ItemInstance", this, player, null);
			}
			player.sendPacket(new SystemMessage(SystemMessageId.TIME_LIMITED_ITEM_DELETED));
			// delete from world
			FuzeWorld.getInstance().exitWorld(this);
		}
	}
	
	int _itemMask = 0;
	
	/**
	 * 获得 物品的 使用掩码(能用使用，追星等)
	 * @return
	 */
	public short getItemMask(){
		
		if( _itemMask > 0 ){
			return (short) _itemMask;
		}
		
		//能否绑定
		if( _item.getCanBinding() ){
			_itemMask |=  0x01;
		}
		//能否合成
		if( _item.getCanComposite() ){
			_itemMask |=  0x01 << 1;
		}
		//能否鉴定
		if( _item.getCanIdentify() ){
			_itemMask |=  0x01 << 2;
		}
		//能否铭刻
		if( _item.getCanInscribe() ){
			_itemMask |= 0x01 << 3;
		}
		//能否追星
		if( _item.getCanStar() ){
			_itemMask |= 0x01 << 4;
		}
		//能否使用
		if( _item.getCanuse() ){
			_itemMask |= 0x01 << 5;
		}
		
		
		return (short) _itemMask;
		
	}

	public long get_time() {
		return _time;
	}

	public void set_time(long time) {
		_time = time;
	}

	public void scheduleLifeTimeTask() {
		if (!isTimeLimitedItem())
			return;
		if (getRemainingTime() <= 0)
			endOfLife();
		else {
			if (_lifeTimeTask != null)
				_lifeTimeTask.cancel();
			_lifeTimeTask = new Timer(getRemainingTime(), false, new ScheduleLifeTimeTask(this));
			_lifeTimeTask.start();

		}
	}

	public class ScheduleLifeTimeTask implements Runnable {
		private final L2ItemInstance _limitedItem;

		public ScheduleLifeTimeTask(L2ItemInstance item) {
			_limitedItem = item;
		}

		public void run() {
			try {
				if (_limitedItem != null)
					_limitedItem.endOfLife();
			} catch (Exception e) {
				_log.error("Item scheduleLifeTimeTask error",Config.SERVER_ID, e);
			}
		}
	}

	@Override
	public void sendInfo(FuzePcInstance activeChar) {
		activeChar.sendPacket(new SpawnItem(this));
	}

}
